package com.raymond.cmpp.session;

import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONObject;
import com.google.common.primitives.Bytes;
import com.raymond.client.constants.GlobalConstants;
import com.raymond.client.handler.RecvBusinessHandler;
import com.raymond.client.handler.RespBusinessHandler;
import com.raymond.client.msg.MessageManages;
import com.raymond.client.netty.AgreementDecoder;
import com.raymond.client.netty.MsgDecoder;
import com.raymond.client.netty.MsgEncoder;
import com.raymond.client.session.AbstractClientSession;
import com.raymond.client.thread.ThreadPool;
import com.raymond.client.utils.SequenceIdUtil;
import com.raymond.cmpp.config.CmppClientSocketConfig;
import com.raymond.cmpp.msg.request.ActiveTestRequestMessage;
import com.raymond.cmpp.msg.request.ConnectRequestMessage;
import com.raymond.cmpp.msg.request.TerminateRequestMessage;
import com.raymond.cmpp.msg.response.ConnectResponseMessage;
import io.netty.channel.Channel;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * 简单的mq连接session
 *
 * @author :  raymond
 * @version :  V1.0
 * @date :  2022-11-01 10:25
 */
public class CmppClientSession extends AbstractClientSession {

    private static final Logger logger = LoggerFactory.getLogger(CmppClientSession.class);

    private int loginStatus = -1;

    CmppClientSession(CmppClientSessionManager sessionManager, CmppClientSocketConfig socketConfig) {
        super(sessionManager, socketConfig);
    }

    @Override
    protected void fireChannelActive(Channel channel) {
        ChannelPipeline pipeline = channel.pipeline();
        CmppClientSessionManager sessionManager = (CmppClientSessionManager)super.sessionManager;
        pipeline.addFirst(new RecvBusinessHandler(sessionManager.getHandlerProcessors(), null));
        pipeline.addFirst(new RespBusinessHandler(msgManager));
        pipeline.addFirst(new MsgEncoder(isV3() ? sessionManager.getCodec3() : sessionManager.getCodec2()));
        pipeline.addFirst(new MsgDecoder(isV3() ? sessionManager.getCodec3() : sessionManager.getCodec2()));
        pipeline.addFirst(new IdleStateHandler(0, 0, 60));
        pipeline.addFirst(new AgreementDecoder());
        doLogin();
    }

    private void doLogin() {
        CmppClientSocketConfig socketConfig = (CmppClientSocketConfig) this.socketConfig;
        // TODO 发送连接请求 ,创建密码
        ConnectRequestMessage req = new ConnectRequestMessage(SequenceIdUtil.getSequenceId());
        req.setSourceAddr(socketConfig.getSourceAddr());
        String timestamp = getCmppData();
        req.setTimestamp(Integer.parseInt(timestamp));
        req.setVersion((short) socketConfig.getVersion());
        byte[] userBytes = socketConfig.getSourceAddr().getBytes(GlobalConstants.DEFAULT_TRANSPORT_CHARSET);
        byte[] pwdBytes = socketConfig.getPassword().getBytes(GlobalConstants.DEFAULT_TRANSPORT_CHARSET);
        byte[] timestampBytes = timestamp.getBytes(GlobalConstants.DEFAULT_TRANSPORT_CHARSET);
        req.setAuthenticatorSource(MD5.create().digest(Bytes.concat(userBytes, new byte[9], pwdBytes, timestampBytes)));
        loginStatus = -2;
        MessageManages messageManages = syncSend(req);
        loginStatus = messageManages.getResp() == null ? -2 : (int) ((ConnectResponseMessage)messageManages.getResp()).getStatus();
        logger.info("session Start :Send CmppConnectRequestMessage seq :{}, messageManages:{}",
                req.getSequenceId(), JSONObject.toJSONString(messageManages));
    }

    public boolean isV3() {
        CmppClientSocketConfig socketConfig = (CmppClientSocketConfig) this.socketConfig;
        return socketConfig.getVersion() == 0X30;
    }

    @Override
    public synchronized void shutdown() throws InterruptedException {
        syncSend(new TerminateRequestMessage(SequenceIdUtil.getSequenceId()));
        super.shutdown();
    }

    public int getLoginStatus() {
        return loginStatus;
    }

    public String getCmppData() {
        return DateUtil.format(new Date(), "MMddHHmmss");
    }
    @Override
    public Object getHeartbeatRequest() {
        return new ActiveTestRequestMessage(SequenceIdUtil.getSequenceId());
    }
}
